package com.spzx.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.vo.ProductSkuVo;
import com.spzx.user.domain.UserBrowseHistory;
import com.spzx.user.mapper.UserBrowseHistoryMapper;
import com.spzx.user.service.IUserBrowseHistoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户浏览记录表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2024-11-18
 */
@Service
public class UserBrowseHistoryServiceImpl extends ServiceImpl<UserBrowseHistoryMapper, UserBrowseHistory> implements IUserBrowseHistoryService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserBrowseHistoryMapper userBrowseHistoryMapper;


    private String getBrowseHistoryKey(Long userId) {
        return "user:" + userId + ":browseHistoryKey";
    }

    @Override
    public void saveUserBrowseHistory(Long skuId) {


        // 获取当前登录用户ID
        Long userId = SecurityUtils.getLoginUser().getUserid();
        // 获取当前登录用户名
        String userName = SecurityUtils.getLoginUser().getUsername();
        if (userId == 0 || userName == null) {
            throw new RuntimeException("当前用户获取不到");
        } else {
            // 构建“用户”浏览历史的Hash结构Key，格式为 user:用户ID:browseHistoryKey
            String browseHistoryKey = getBrowseHistoryKey(userId);

            // 创建Hash结构绑定操作对象，便于对Hash进行操作
            BoundHashOperations<String, String, UserBrowseHistory> hashOps = redisTemplate.boundHashOps(browseHistoryKey);
            UserBrowseHistory userBrowseHistory;
            if (Boolean.FALSE.equals(hashOps.hasKey(skuId.toString()))) {
                // 该商品在浏览历史中已存在在缓存中，则查询数据库中是否存在
                userBrowseHistory = userBrowseHistoryMapper.selectOne(
                        new LambdaQueryWrapper<UserBrowseHistory>()
                                .eq(UserBrowseHistory::getUserId, userId)
                                .eq(UserBrowseHistory::getSkuId, skuId));
                if (userBrowseHistory != null) {
                    // 数据库中存在该商品，则更新浏览时间
                    userBrowseHistoryMapper.update(
                            null,
                            new LambdaUpdateWrapper<UserBrowseHistory>()
                                    .eq(UserBrowseHistory::getUserId, userId)
                                    .eq(UserBrowseHistory::getSkuId, skuId)
                                    .set(UserBrowseHistory::getUpdateBy, userName)
                    );
                    hashOps.put(browseHistoryKey, userBrowseHistory);
                } else {
                    // 数据库中不存在该商品，则更新数据库，并更新缓存
                    userBrowseHistory = new UserBrowseHistory();
                    userBrowseHistory.setUserId(userId);
                    userBrowseHistory.setSkuId(skuId);
                    userBrowseHistory.setCreateBy(userName);
                    userBrowseHistoryMapper.insert(userBrowseHistory);
                    hashOps.put(browseHistoryKey, userBrowseHistory);
                }
            } else {
                // 该商品浏览历史在缓存中不存在，则查询数据库中是否存在
                userBrowseHistory = userBrowseHistoryMapper.selectOne(
                        new LambdaQueryWrapper<UserBrowseHistory>()
                                .eq(UserBrowseHistory::getUserId, userId)
                                .eq(UserBrowseHistory::getSkuId, skuId));
                if (userBrowseHistory != null) {
                    userBrowseHistoryMapper.update(
                            null,
                            new LambdaUpdateWrapper<UserBrowseHistory>()
                                    .eq(UserBrowseHistory::getUserId, userId)
                                    .eq(UserBrowseHistory::getSkuId, skuId)
                                    .eq(UserBrowseHistory::getUpdateBy, userName)
                    );
                    hashOps.put(browseHistoryKey, userBrowseHistory);
                } else {
                    // 数据库中不存在该商品，则更新数据库，并更新缓存
                    userBrowseHistory = new UserBrowseHistory();
                    userBrowseHistory.setUserId(userId);
                    userBrowseHistory.setSkuId(skuId);
                    userBrowseHistory.setCreateBy(userName);
                    userBrowseHistoryMapper.insert(userBrowseHistory);
                    hashOps.put(browseHistoryKey, userBrowseHistory);
                }


            }

        }
    }


    @Autowired
    private RemoteProductService remoteProductService;
    @Override
    public List<ProductSkuVo> getUserBrowseHistoryList() {
        // 获取浏览记录列表
        List<UserBrowseHistory> userBrowseHistoryList = userBrowseHistoryMapper.selectList(null);
        if (userBrowseHistoryList != null) {
            Long userId = SecurityUtils.getLoginUser().getUserid();
            return super.lambdaQuery()
                    .eq(UserBrowseHistory::getUserId, userId)
                    .list()
                    .stream()
                    .map(
                            userBrowseHistory -> {
                                R<ProductSkuVo> productSkuVoResult = remoteProductService.getProductSku(userBrowseHistory.getSkuId(), SecurityConstants.INNER);
                                if (R.FAIL == productSkuVoResult.getCode()) {
                                    throw new ServiceException(productSkuVoResult.getMsg());
                                }
                                ProductSkuVo productSku = productSkuVoResult.getData();
                                return productSku;
                            }).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }


}
